<template>
  <div class="apartment-group-module" v-loading="formated_list.length === 0">
    <div class="apartment" v-for="(department, index) in formated_list" :key="department.title">
      <div
        :class="{
          apart_title: true,
          unfolded_apart: !isFolded(department.title)
        }"
        @click="handleApartFolder(department.title, index)"
      >
        <span>{{ department.title }}</span>
        <i class="iconfont icon-arrow-up" />
      </div>
      <ul
        ref="ul_list"
        :class="[
          {
            apart_employee_list: true,
            folded: isFolded(department.title)
          },
          `ul_list_${index}`
        ]"
      >
        <li
          v-for="employee in department.employees"
          :key="employee.name"
          :class="[
            {
              apart_employee: true,
              // 'level-1': employee.level === 1,
              'is-selected': employee.name === selected_employee.name
            },
            computedLevel(employee.level)
          ]"
          @click="selectEmployee(employee.name, department.title)"
        >
          <div class="employee_infos">
            <span>姓名：{{ employee.name }}</span>
            <span>职位：{{ employee.position }}</span>
          </div>
          <i class="iconfont icon-editor"></i>
        </li>
      </ul>
    </div>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'
import { Component, Emit, Prop, Ref, Watch } from 'vue-property-decorator'
import { ApartmentListType } from '@/interface/Basic'
import { Dictionary } from 'vue-router/types/router'
@Component
class ApartmentGroup extends Vue {
  @Ref() ul_list!: HTMLUListElement | HTMLUListElement[]
  // 部门及下属员工列表
  @Prop({ required: true }) list!: ApartmentListType
  @Prop() activeEmployee!: {
    name: string
    department: string
  }
  // 是否开启手风琴模式
  @Prop({ default: false }) accordion!: boolean
  formated_list: ApartmentListType = []
  active_aparts: string[] = []
  selected_employee: Dictionary<string> = {}
  @Watch('list', { immediate: true })
  l_handler(newVal: ApartmentListType) {
    this.formated_list = newVal.map(li => {
      // 员工列表 li.employee 排序
      const map = new Map()
      for (const employee of li.employees) {
        if (!employee.level) {
          map.set('default', [...(map.get('default') ? map.get('default') : []), employee])
        } else {
          map.set(employee.level, [
            ...(map.get(employee.level) ? map.get(employee.level) : []),
            employee
          ])
        }
      }
      const default_arr = map.get('default')
      map.delete('default')
      const result = [...map.keys()]
        .sort((a, b) => a - b)
        .reduce((accu, next) => {
          return [...accu, ...map.get(next)]
        }, [])
      li.employees = [...result, ...default_arr]
      return li
    })
  }
  @Watch('activeEmployee', { immediate: true, deep: true })
  ae_handler(newVal: { name: string; department: string }) {
    this.$nextTick(() => {
      this.list.forEach(li => {
        li.employees.forEach(employee => {
          if (employee.name === newVal.name && li.title === newVal.department) {
            this.active_aparts = [li.title]
            this.selected_employee = newVal
          }
        })
      })
    })
  }
  @Emit()
  selectEmployee(name: string | number, department: string) {
    return { name, department }
  }
  // methods
  isFolded(title: string) {
    return !this.active_aparts.includes(title)
  }
  computedLevel(level: string | number) {
    if (!level) return ''
    else return `level-${level}`
  }
  getUlLiSTElement(index: number) {
    const refs = this.ul_list
    if (Array.isArray(refs)) {
      for (const ref of refs) {
        if (ref.className.indexOf(`ul_list_${index}`) !== -1) return ref
      }
    } else return refs
  }
  animateFolder(index: number, type: 'close' | 'open') {
    const ref = this.getUlLiSTElement(index)
    if (ref === undefined) return
    const { height } = ref.getBoundingClientRect()
    if (type === 'close') {
      ref.animate([{ height: height + 'px' }, { height: 0 }], { duration: 300 })
    } else {
      ref.animate([{ height: 0 }, { height: height + 'px' }], { duration: 300 })
    }
  }
  handleApartFolder(title: string, index: number) {
    if (this.accordion) {
      this.handleApartAccordion(title, index)
      return
    }
    const idx = this.active_aparts.indexOf(title)
    if (idx === -1) {
      // 折叠状态
      this.active_aparts.push(title)
      this.$nextTick(() => {
        this.animateFolder(index, 'open')
      })
    } else {
      // 展开状态
      this.active_aparts.splice(idx, 1)
      this.animateFolder(index, 'close')
    }
  }
  handleApartAccordion(title: string, index: number) {
    if (this.active_aparts.length === 0) {
      // 所有部门均处于折叠状态
      this.active_aparts = [title]
      this.$nextTick(() => {
        this.animateFolder(index, 'open')
      })
    } else if (this.active_aparts[0] !== title) {
      // 其他部门处于折叠状态
      const origin_title = this.active_aparts[0]
      const idx = this.formated_list.findIndex(li => li.title === origin_title)
      this.animateFolder(idx, 'close')
      this.active_aparts = [title]
      this.$nextTick(() => {
        this.animateFolder(index, 'open')
      })
    } else {
      // 展开状态
      this.active_aparts = []
      this.animateFolder(index, 'close')
    }
  }
}
export default ApartmentGroup
</script>

<style lang="less" scoped>
@import '~@/styles/theme.less';
@import '~@/styles/layout.less';
.apartment-group-module {
  width: 100%;
  .apartment {
    .apart_title {
      box-sizing: border-box;
      position: relative;
      width: 100%;
      padding: 12px 8px;
      padding-left: 15px;
      #color(color, --primary-text-color);
      #flex(row, center, space-between);
      i {
        transition: all 0.5s ease;
      }
    }
    .apart_title::before {
      content: '';
      width: 5px;
      position: absolute;
      left: 0;
      top: 0;
      bottom: 0;
      #color(background-color, --primary-blue-color);
    }
    .unfolded_apart {
      i {
        transform: rotate(180deg);
      }
    }
    .apart_employee_list {
      overflow: hidden;
      #color(background-color, --primary-bg-color);
      .apart_employee {
        padding: 12px 8px;
        padding-left: 20px;
        border-bottom: solid 1px;
        font-size: 14px;
        transition: all 0.5s ease;
        cursor: pointer;
        #flex(row, center, space-between);
        #color(color, --primary-text-color);
        #color(border-color, --primary-border-color);
        #color(background-color, --primary-bg-color);
        .employee_infos {
          #flex(column, flex-start, space-between);
        }
        i {
          font-size: 20px;
        }
      }
      .apart_employee:hover {
        transform: translateY(-5px);
        #shadow-color(0, 4px, 8px, 0, --primary-shadow-color);
      }
      .level-1 {
        color: #ffffff;
        #color(background-color, --heavier-red-color);
      }
      .level-2 {
        color: #ffffff;
        #color(background-color, --primary-red-color);
      }
      .level-3 {
        color: #ffffff;
        #color(background-color, --lighter-red-color);
      }
      .is-selected {
        color: #ffffff;
        #color(background-color, --primary-green-color);
      }
    }
    .folded {
      height: 0;
    }
  }
}
</style>
